Understanding Automatic Properties

When .NET 3.5 was released, the C# language offered yet another way to define simple encapsulation services with minimal code, using automatic property syntax. To illustrate, create a new C# Console Application project named AutoProps. Now, insert a new C# class file (Car.cs) that defines the following class, which encapsulates a single point of data using classic property syntax.

// A Car type using standard property
// syntax.
class Car
{
    private string carName = string.Empty;
    public string PetName
    {
        get { return carName; }
        set { carName = value; }
    }
}

While it is very true that most C# properties contain business rules within their set scope, it is not too uncommon that some properties literally have nothing more to do than simply assign and return the value straightaway as you see here. In these cases, it can become rather verbose to define private backing fields and simple property definitions multiple times. By way of an example, if you are modeling a class that requires 15 private points of field data, you end up authoring 15 related properties that are little more than thin wrappers for encapsulation services.

To streamline the process of providing simple encapsulation of field data, you may use automatic property syntax. As the name implies, this feature will offload the work of defining a private backing field and the related C# property member to the compiler using a new bit of syntax. Consider the reworking of the Car class, which uses this syntax to quickly create three properties:

//class Car
{
    // Automatic properties!
    public string PetName { get; set; }
    public int Speed { get; set; }
    public string Color { get; set; }
}

When defining automatic properties, you simply specify the access modifier, underlying data type, property name, and empty get/set scopes. At compile time, your type will be provided with an autogenerated private backing field and a fitting implementation of the get/set logic.

Note The name of the autogenerated private backing field is not visible within your C# code base. The only way to see it is to make use of a tool such as ildasm.exe.

Unlike traditional C# properties, however, it is not possible to build read-only or write-only automatic properties. While you might think you can just omit the get; or set; within your property declaration as follows:

// Read-only property? Error!
public int MyReadOnlyProp { get; }

// Write only property? Error!
public int MyWriteOnlyProp { set; }

this will result in a compiler error. When you are defining an automatic property, it must support both read and write functionality. However, it is possible to implement an automatic property which defines a more restrictive get or set:

// Public get, protected set!
// You could also set a get / set to private.
public int SomeOtherProperty { get; protected set; }

Interacting with Automatic Properties

Because the compiler will define the private backing field at compile time, the class defining automatic properties will always need to use property syntax to get and set the underlying value. This is important to note because many programmers make direct use of the private fields within a class definition, which is not possible in this case. For example, if the Car class were to provide a DisplayStats() method, it would need to implement this method using the property name:

class Car
{
    // Automatic properties!
    public string PetName { get; set; }
    public int Speed { get; set; }
    public string Color { get; set; }

    public void DisplayStats()
    {
        Console.WriteLine("Car Name: {0}", PetName);
        Console.WriteLine("Speed: {0}", Speed);
        Console.WriteLine("Color: {0}", Color);
    }
}

When you are using an object defined with automatic properties, you will be able to assign and obtain the values using the expected property syntax:

static void Main(string[] args)
{
    Console.WriteLine("***** Fun with Automatic Properties *****\n");

    Car c = new Car();
    c.PetName = "Frank";
    c.Speed = 55;
    c.Color = "Red";

    Console.WriteLine("Your car is named {0}? That's odd...",
        c.PetName);
    c.DisplayStats();

    Console.ReadLine();
}

Regarding Automatic Properties and Default Values

When you use automatic properties to encapsulate numerical or Boolean data, you are able to use the autogenerated type properties straightaway within your code base, as the hidden backing fields will be assigned a safe default value that can be used directly. However, be very aware that if you use automatic property syntax to wrap another class variable, the hidden private reference type will also be set to a default value of null.

Consider the following new class named Garage, which makes use of two automatic properties:

class Garage
{
    // The hidden int backing field is set to zero!
    public int NumberOfCars { get; set; }

    // The hidden Car backing field is set to null!
    public Car MyAuto { get; set; }
}

Given C#'s default values for field data, you would be able to print out the value of NumberOfCars as is (as it is automatically assigned the value of zero), but if you directly invoke MyAuto, you will receive a "null reference exception" at runtime, as the Car member variable used in the background has not been assigned to a new object:

static void Main(string[] args)
{
    ...
    Garage g = new Garage();

    // OK, prints default value of zero.
    Console.WriteLine("Number of Cars: {0}", g.NumberOfCars);

    // Runtime error! Backing field is currently null!
    Console.WriteLine(g.MyAuto.PetName);
    Console.ReadLine();
}

Given that the private backing fields are created at compile time, you will be unable to make use of C# field initialization syntax to allocate the reference type directly with the new keyword. Therefore, this work will need to be done with class constructors to ensure the object comes to life in a safe manner. For example:

class Garage
{
    // The hidden backing field is set to zero!
    public int NumberOfCars { get; set; }

    // The hidden backing field is set to null!
    public Car MyAuto { get; set; }

    // Must use constructors to override default
    // values assigned to hidden backing fields.
    public Garage()
    {
        MyAuto = new Car();
        NumberOfCars = 1;
    }

    public Garage(Car car, int number)
    {
        MyAuto = car;
        NumberOfCars = number;
    }
}

With this update, you could now place a Car object into the Garage object as so:

static void Main(string[] args)
{
    Console.WriteLine("***** Fun with Automatic Properties *****\n");

    // Make a car.
    Car c = new Car();
    c.PetName = "Frank";
    c.Speed = 55;
    c.Color = "Red";
    c.DisplayStats();

    // Put car in the garage.
    Garage g = new Garage();
    g.MyAuto = c;
    Console.WriteLine("Number of Cars in garage: {0}", g.NumberOfCars);
    Console.WriteLine("Your car is named: {0}", g.MyAuto.PetName);

    Console.ReadLine();
}

As you most likely agree, this is a very nice feature of the C# programming language, as you can define a number of properties for a class using a streamlined syntax. Be aware of course that if you are building a property that requires additional code beyond getting and setting the underlying private field (such as data validation logic, writing to an event log, communicating with a database, etc.), you will be required to define a "normal" .NET property type by hand. C# automatic properties never do more than provide simple encapsulation for an underlying piece of (compiler generated) private data.